package com.smart.stock.module.spider.util;

import com.smart.stock.common.util.cache.EhcacheUtil;
import com.smart.stock.module.spider.jobSpiderWeb.tradingdate.TradingDateSpider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.FutureTask;

/**
 * 交易时间工具类
 *
 * @author chenguoxiang
 * @create 2019-03-28 12:57
 **/
@Slf4j
@Component
public class TradingDateUtil {

    private final String CACHE_NAME = "TradingDate";
    public static DateTimeFormatter defaultFormater = DateTimeFormatter.ofPattern("yyyyMMdd");
    public static DateTimeFormatter defaultFormaterDateTime = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    public static DateTimeFormatter defaultFormaterTrading = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    @Autowired
    private EhcacheUtil ehcacheUtil;


    /**
     * 以20190606这种方式返回当前日期
     *
     * @return
     */
    public static String getDateYYYYMMdd() {
        LocalDate localDate = LocalDate.now();
        return defaultFormater.format(localDate);
    }

    /**
     * 得到当前时间以数字形式返回  包含时分秒
     *
     * @return
     */
    public static String getDateTime() {
        LocalDateTime localDate = LocalDateTime.now();
        return defaultFormaterDateTime.format(localDate);
    }

    /**
     * 当前减传入参数值得到计算后的日期
     *
     * @param year              减去年份数
     * @param month             减去月份数
     * @param day               减去天数
     * @param dateFormatPattern 格式化后的日期格式 如（yyyyMMdd）
     * @return
     */
    public static String minusDateNow(int year, int month, int day, String dateFormatPattern) {
        DateTimeFormatter sf = DateTimeFormatter.ofPattern(dateFormatPattern);
        LocalDate localDate = LocalDate.now();
        return sf.format(localDate.minusYears(year).minusMonths(month).minusDays(day));
    }
    public static String minusDate(int year, int month, int day,String date) {
        LocalDate localDate = string2date(date);
        return defaultFormater.format(localDate.minusYears(year).minusMonths(month).minusDays(day));
    }
    public static String plusDateNow(int year, int month, int day, String dateFormatPattern) {
        DateTimeFormatter sf = DateTimeFormatter.ofPattern(dateFormatPattern);
        LocalDate localDate = LocalDate.now();
        return sf.format(localDate.plusYears(year).plusMonths(month).plusDays(day));
    }
    public static String plusDate(int year, int month, int day,String date) {
        LocalDate localDate = string2date(date);
        return defaultFormater.format(localDate.plusYears(year).plusMonths(month).plusDays(day));
    }
    /**
     * long timestap 转换成年月日字符串
     * @param timestamp
     * @return
     */
    public static String long2string(Long timestamp){
            Instant instant = Instant.ofEpochMilli(timestamp);
            ZoneId zone = ZoneId.systemDefault();
            LocalDateTime localDate= LocalDateTime.ofInstant(instant, zone);
            return defaultFormater.format(localDate);
    }

    public static LocalDate string2date(String str){
        LocalDate localDate = LocalDate.parse(str, defaultFormater);
        return localDate;
    }

    /**
     * 当前是否为交易时间
     *
     * @return
     */
    public boolean isTradingTimeNow() {
        try {
            LocalDateTime dateTime = LocalDateTime.now();
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            String day = dtf.format(dateTime);
            if (isTradingDay(day)) {
                if (isTradingTime(dateTime.getHour(), dateTime.getMinute())) {
//                    log.info("现在是交易时间");
                    return true;
                } else {
//                    log.info("现在不是交易时间");
                    return false;
                }
            }
        } catch (Exception ex) {
            log.error("{}", ex);
            ex.printStackTrace();
        }
        return false;
    }

    /**
     * 今天是否是交易日
     *
     * @return
     * @throws Exception
     */
    public boolean isTradingDay() {
        LocalDateTime dateTime = LocalDateTime.now();
        String day = defaultFormater.format(dateTime);
        try {
            return isTradingDay(day);
        } catch (Exception e) {
            log.error("{}", e);
            e.printStackTrace();
            return false;
        }
    }
//    public boolean isTradingDay() {
//        LocalDateTime dateTime = LocalDateTime.now();
//        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//        String day = dtf.format(dateTime);
//        try {
//            return isTradingDay(day);
//        } catch (Exception e) {
//            log.error("{}", e);
//            e.printStackTrace();
//            return false;
//        }
//    }

    /**
     * 是否为交易日
     *
     * @param date 日期例如：2019-03-28
     * @return
     */
    public boolean isTradingDay(String date) throws Exception {
        if (!date.matches("\\d{4}\\-\\d{2}\\-\\d{2}")) {
//        if (!date.matches("\\d{4}\\d{2}\\d{2}")) {
            throw new Exception("传入日期格式不正确：yyyy-MM-dd");
        }
        if (ehcacheUtil.contrainKey(CACHE_NAME, date)) {
            return (boolean) ehcacheUtil.getKey(CACHE_NAME, date);
        } else {
            String month = date.substring(0, 7);
//            String month = date.substring(0, 4)+"-"+date.substring(4, 6);
            TradingDateSpider spider = new TradingDateSpider(month);
            FutureTask<Map<String, Boolean>> futureTask = new FutureTask<Map<String, Boolean>>(spider);
            new Thread(futureTask).start();
            Map<String, Boolean> map = futureTask.get();
            map.keySet().stream().forEach(key -> {
                ehcacheUtil.addKey(CACHE_NAME, key, map.get(key));
            });
            return map.get(date);
        }
    }

    /**
     * 是否为交易日间 9：30 ~ 11：30 13：00 ~ 15：00
     *
     * @param hour
     * @param minute
     * @return
     */
    public boolean isTradingTime(int hour, int minute) {
        if (hour >= 9 && hour <= 11) {
            if (hour == 9 && minute < 30) {
                //未到9点半
                return false;
            } else if (hour == 11 && minute > 30) {
                //超过11点半
                return false;
            } else {
                return true;
            }
        } else if (hour >= 13 && hour <= 15) {
            if (hour == 15 && minute >= 1) {
                return false;
            }
            //下午1点到3点
            return true;
        }
        return false;
    }

    /**
     * 获取时间段的边界
     * @param nYearsAgo
     * @return
     */
    public static List<String> getDayBounds(int nYearsAgo,int nMonthsAgo,int nDaysAgo){
        String startDate= minusDateNow(nYearsAgo,nMonthsAgo,nDaysAgo,"yyyyMMdd");
        String end=getDateYYYYMMdd();
        return Arrays.asList(startDate,end);
    }

    public String formateDateStr(String date){
        return date.substring(0, 4)+"-"+date.substring(4, 6)+"-"+date.substring(6, 8);
    }

    public int getDaysBetween(String beginDate, String endDate) throws Exception {
        LocalDate beginDateLocal = LocalDate.parse(formateDateStr(beginDate), defaultFormaterTrading);
        LocalDate endDateLocal = LocalDate.parse(formateDateStr(endDate), defaultFormaterTrading);
        int days = 0;
        int daysTrading = 0;
        while (beginDateLocal.isBefore(endDateLocal)){
            if (isTradingDay(beginDateLocal.format(defaultFormaterTrading))) {
                daysTrading++;
            }

            days++;
            beginDateLocal = beginDateLocal.plusDays(1);
            if (beginDateLocal.isEqual(endDateLocal)) {
                return daysTrading;
            }
        }
        return daysTrading;
    }

    public static void main(String[] args) throws Exception {
        System.out.println(new TradingDateUtil().isTradingDay("20210724"));;
    }
}
